﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using Thor.Domain;

namespace Thor.Domain.Configuration
{
    /// <summary>
    /// Manages Thor's calendars.
    /// </summary>
    public class CalendarManager
    {
        #region Fields

        private ICalendarRepository _calendarRepository = null;
        private List<Calendar> _calendars = null;

        #endregion

        #region Constructors

        public CalendarManager(ICalendarRepository calendarRepository)
        {
            _calendarRepository = calendarRepository;
        }

        #endregion

        #region Properties

        /// <summary>
        /// List of calendars to monitor.
        /// </summary>
        public List<Calendar> Calendars
        {
            get
            {
                if (_calendars == null)
                {
                    _calendars = _calendarRepository.Fetch();

                    if (_calendars == null)
                        _calendars = new List<Calendar>();
                    else
                    {
                        foreach (Calendar cal in _calendars)
                        {
                            cal.ConvertFromUtc();
                        }
                    }
                }

                return _calendars;
            }
            set { _calendars = value; }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Inserts a calendar.
        /// </summary>
        /// <param name="calendar"></param>
        public void Insert(Calendar calendar)
        {
            calendar.ConvertToUtc();

            if (calendar.Id == Guid.Empty)
                calendar.Id = Guid.NewGuid();

            _calendarRepository.Insert(calendar);
        }

        /// <summary>
        /// Updates a calendar.
        /// </summary>
        /// <param name="calendar"></param>
        public void Update(Calendar calendar)
        {
            calendar.ConvertToUtc();

            _calendarRepository.Update(calendar);
        }

        /// <summary>
        /// Deletes a calendar.
        /// </summary>
        /// <param name="calendar"></param>
        public void Delete(Calendar calendar)
        {
            _calendarRepository.Delete(calendar);
        }

        /// <summary>
        /// Returns a single calendar.
        /// </summary>
        /// <param name="calendarId"></param>
        /// <returns></returns>
        public Calendar GetCalendar(Guid calendarId)
        {
            var calendar = _calendarRepository.Fetch(calendarId);

            if (calendar != null)
            {
                calendar.ConvertFromUtc();
            }

            return calendar;
        }

        public Calendar GetCalendar(string calendarEmailAddress)
        {
            var calendar = (from item in this.Calendars
                            where item.CalendarEmail == calendarEmailAddress
                            select item).FirstOrDefault();

            return calendar;
        }

        /// <summary>
        /// Gets a concrete implementation of ICalendarRepository.
        /// </summary>
        /// <param name="assemblyPath">Full path to the assembly.</param>
        /// <param name="typeName">Full type name of the type in the assembly that implements ICalendarRepository.</param>
        /// <returns></returns>
        public static ICalendarRepository GetRepository(string assemblyPath, string typeName, Dictionary<string, object> repositoryParameters)
        {
            //Load the assembly from the specified path.
            Assembly assembly = Assembly.LoadFile(assemblyPath);

            //Load the type
            Type type = assembly.GetType(typeName);

            //Get the constructor
            Type[] constructorTypes = new Type[1];
            constructorTypes[0] = typeof(Dictionary<string, object>);
            ConstructorInfo constructorInfo = type.GetConstructor(constructorTypes);

            //Invoke the constructor and return a new instance
            if (constructorInfo != null)
                return constructorInfo.Invoke(new object[] { repositoryParameters }) as ICalendarRepository;

            return null;
        }



        #endregion
    }
}
